package com.siteseat.crudeq.kernel;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.util.HashMap;
import java.util.Map;

import com.siteseat.common.exception.InternalException;
import com.siteseat.crudeq.common.raw.Constants;

/**
 * 
 */
public class ChunkFileFilter implements Constants, FilenameFilter {

  private KernelFactory factory;
  
  private QueueProfile              profile;

  private Map<Long, ChunkInfo> result     = new HashMap<Long, ChunkInfo>();

  private long                 maxChunkId = 0;

  /**
   * @param log
   */
  public ChunkFileFilter( KernelFactory factory, QueueProfile profile ) {
    this.factory = factory;
    this.profile = profile;
  }

  /**
   * Gets the factory
   *
   * @return the factory
   */
  public KernelFactory getFactory() {
    return factory;
  }

  /**
   * Gets the result
   * 
   * @return the result
   */
  public Map<Long, ChunkInfo> getResult() {
    return result;
  }

  /**
   * Gets the profile
   * 
   * @return the profile
   */
  public QueueProfile getProfile() {
    return profile;
  }

  /**
   * @param f
   * @return
   */
  public static String extractFileTitle( File f ) {
    String p = f.getAbsolutePath();
    if( p.endsWith( CHUNK_FILE_DOT_EXTENSION ) == false ) {
      return null;
    }

    int end = p.lastIndexOf( '.' );
    if( end <= 0 ) {
      return null;
    }

    int begin = p.lastIndexOf( File.separator );
    if( begin <= 0 ) {
      return null;
    }

    return p.substring( begin + 1, end );
  }

  /**
   * @param dir
   * @param name
   * @return
   */
  @Override
  public boolean accept( File dir, String name ) {
    File f = new File( dir, name );

    if( f.isDirectory() ) {
      f.list( this );
      return false;
    }

    if( f.canRead() == false ) {
      throw new InternalException( "Cannot read file <" + f.getAbsolutePath() + ">" );
    }

    String title = extractFileTitle( f );
    if( title == null ) {
      return false;
    }

    Long cid;
    try {
      cid = Long.valueOf( Long.parseLong( title ) );
    } catch( NumberFormatException e ) {
      return false;
    }

    if( cid.longValue() > this.maxChunkId ) {
      this.maxChunkId = cid.longValue();
    }
    
    if( this.result.containsKey( cid ) ) {
      throw new InternalException( "Duplicated chunk file with same id: " + cid + ", the new one <"
              + f.getAbsolutePath() + " is ignored" );
    }

    try {
      this.result.put( cid, getFactory().newChunkInfo( profile, f, cid ) );
    } catch( FileNotFoundException e ) {
      throw new InternalException( "Cannot read file <" + f.getAbsolutePath() + ">" );
    }    

    return true;
  }

  /**
   * Gets the maxChunkId
   * 
   * @return the maxChunkId
   */
  public long getMaxChunkId() {
    return maxChunkId;
  }

}